package com.hifar.utils;

import com.alibaba.fastjson.JSONArray;
import com.hifar.fw.utils.lang.StringUtils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.tssk.kylx.fw.json.JsonUtils;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ItextpdfUtil {
    /**
     * @param newfile 合并后的文件路径
     * @MethodName: mergePdfFiles
     * @Description:用itext将多个PDF文件合并为1个pdf,并加入页码
     * @Param: * @param files  原始文件list集合
     * @Return: java.lang.String
     * @Author: lyk
     * @Date: 16:17 2020/3/29
     **/
    public static String mergePdfFiles(List<String> files, String newfile) {
        String sumFile = "";
        Document document = null;
        try {
            PdfReader pdfReader = new PdfReader(files.get(0));
            document = new Document(pdfReader.getPageSize(1));
            //PdfCopy比PdfSmartCopy处理文件快,文件大,PdfSmartCopy处理文档慢,占用内存大,生成的pdf文件小
            PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile));//
            document.open();
            int pagesNum = 0;//总页码
            int pages = 0;//当前页码
            //循环得到总页码,插入页码所需  不要页码可删除
            for (int i = 0; i < files.size(); i++) {
                PdfReader reader = new PdfReader(files.get(i));
                pagesNum += reader.getNumberOfPages();
                reader.close();
            }
            //循环pdf文件,将每个pdf的page拷贝到总的pdf中
            for (int i = 0; i < files.size(); i++) {
                PdfReader reader = new PdfReader(files.get(i));
                PdfCopy.PageStamp stamp;//插入页码所需  不要页码可删除
                int n = reader.getNumberOfPages();
                for (int j = 1; j <= n; j++) {
                    pages++;//插入页码所需  不要页码可删除
                    document.newPage();
                    PdfImportedPage page = copy.getImportedPage(reader, j);
                    stamp = copy.createPageStamp(page);//插入页码所需  不要页码可删除
                    ColumnText.showTextAligned(stamp.getUnderContent(), Element.ALIGN_CENTER,
                            new Phrase(addFont(String.format("第%d页/共%d页", pages, pagesNum))), 300f, 16f, 0f);//插入页码所需  不要页码可删除
//                    stamp.alterContents();//插入页码所需  不要页码可删除
                    copy.addPage(page);
                }
                reader.close();
            }
            pdfReader.close();
            copy.flush();
            copy.close();
            sumFile = newfile;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (document != null) {
                document.close();
            }
        }
        for (String file : files) {
            //必须关闭所有的reader,copy,doc否则文件将被占用,无法删除
            new File(file).delete();
        }
        return sumFile;
    }

    /**
     * @MethodName: addFont
     * @Description:字体的设置
     * @Param: * @param content 内容
     * @Return: com.itextpdf.text.Paragraph 段落
     * @Author: lyk
     * @Date: 15:28 2020/3/29
     **/
    protected static Paragraph addFont(String content) {
        BaseFont baseFont = null;
        try {
            baseFont = baseFont();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Font font = null;
        font = new Font(baseFont, 10f, Font.NORMAL);//设置字体
        return addText(content, font);
    }

    /**
     * @MethodName: baseFont
     * @Description:设置中文字体
     * @Param: * @param
     * @Return: com.itextpdf.text.pdf.BaseFont 中文字体
     * @Author: lyk
     * @Date: 15:28 2020/3/30
     **/
    protected static BaseFont baseFont() throws IOException, org.dom4j.DocumentException {
        BaseFont baseFont = null;
        //自带字体可能会因为adober版本不同造成中文不显示
//        baseFont=BaseFont.createFont("STSong-Light",  "UniGB-UCS2-H",BaseFont.EMBEDDED);//设置中文字体,这里需要itext-asian的jar,自带字体
        try {
            baseFont = BaseFont.createFont("c:/windows/fonts/SIMSUN.TTC,0", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//0宋体,1新宋体
        } catch (DocumentException e) {
            e.printStackTrace();
        }
//        baseFont=BaseFont.createFont("c:/windows/fonts/msyh.ttf",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//微软雅黑
        return baseFont;
    }

    /**
     * @param font 字体
     * @MethodName: addText
     * @Description:插入中文
     * @Param: * @param content 内容
     * @Return: com.itextpdf.text.Paragraph 段落
     * @Author: lyk
     * @Date: 15:28 2020/3/29
     **/
    private static Paragraph addText(String content, Font font) {
        Paragraph paragraph = new Paragraph(content, font);
        paragraph.setAlignment(Element.ALIGN_LEFT);
        return paragraph;
    }

    /**
     * @param destFile 目标文件
     * @param keyMap   key集合
     * @MethodName: insertFormFiledToPdf
     * @Description:向PDF文本域插入文本或图片
     * @Param: * @param srcfile 模版文件
     * @Return: java.util.Map<java.lang.String, java.lang.Object> 插入后的文件
     * @Author: lyk
     * @Date: 15:59 2020/3/30
     **/
    public static Map<String, Object> insertFormFiledToPdf(File srcfile, String destFile, Map<String, Object> keyMap) {
        Map<String, Object> resMap = new HashMap<String, Object>();
        if (srcfile.isFile()) {
            String fileName = srcfile.getName();
            String type = fileName.substring(fileName.lastIndexOf(".") + 1);
            if (type.equals("PDF") || type.equals("pdf")) {
                PdfReader reader;
                FileOutputStream out;
                ByteArrayOutputStream bos;
                PdfStamper stamper;
                try {
                    out = new FileOutputStream(destFile);//输出流
                    reader = new PdfReader(srcfile.toString());//读取pdf
                    bos = new ByteArrayOutputStream();
                    stamper = new PdfStamper(reader, bos);
                    AcroFields fields = stamper.getAcroFields();//所有的域
                    fields.addSubstitutionFont(baseFont());//设置中文字体
                    for (Map.Entry<String, Object> entry : keyMap.entrySet()) {
                        String key = entry.getKey();// key 书签名字
                        Object valueObj = entry.getValue(); // 指定书签位置要插入的值
                        //处理图片,根据域名插入图片
                        if (key.startsWith("QRCode")) {
                            parseImage(stamper, fields, key, (byte[]) valueObj);
                        }else {
                            //在指定域名插入文本
                            matchTagValue(fields, key, StringUtils.trimNull(valueObj));
                        }
                    }
                    stamper.setFormFlattening(true);//如果为false那么生成的PDF文件还能编辑，一定要设为true
                    stamper.close();
                    Document doc = new Document();
                    PdfCopy copy = new PdfCopy(doc, out);
                    doc.open();
                    PdfReader bosReader = new PdfReader(bos.toByteArray());
                    PdfImportedPage importPage = copy.getImportedPage(bosReader, 1);
                    copy.addPage(importPage);
                    reader.close();
                    bosReader.close();
                    out.flush();
                    doc.close();
                    out.close();
                    bos.flush();
                    bos.close();
                    resMap.put("success", true);
                    resMap.put("path", destFile);
                    resMap.put("msg", "文本域插入成功");
                } catch (Exception e) {
                    e.printStackTrace();
                }

            } else {
                resMap.put("success", false);
                resMap.put("msg", "该文件不是pdf文件");
            }
        } else {
            resMap.put("success", false);
            resMap.put("msg", "模版文件不存在");
        }
        return resMap;
    }

    public boolean isJson(String content) {
        return JsonUtils.isJson(content);
    }

    /**
     * @param key
     * @param value
     * @MethodName: matchTagValue
     * @Description:向文本域插入文本
     * @Param: * @param form 域集合
     * @Return: void
     * @Author: lyk
     * @Date: 16:00 2020/3/30
     **/
    private static void matchTagValue(AcroFields fields, String key, String value) {
        try {
            //先判断是否有域名为key的文本域
            String fieldName = fields.getField(key);
            if (fieldName != null) {
                fields.setFieldProperty(key, "textsize", new Float(10), null);//设置字体大小
                fields.setField(key, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param stamper
     * @param fields
     * @param key
     * @param value
     */
    private static void parseImage(PdfStamper stamper, AcroFields fields, String key, byte[] value) {
        //插入图片
        insertImageAtFieldPositions(stamper, fields, key, value);
    }

    /**
     * 向指定坐标插入图片
     *
     * @param stamper
     * @param fields
     * @param key
     * @param bytes
     */
    private static void insertImageAtFieldPositions(PdfStamper stamper, AcroFields fields, String key, byte[] bytes) {
        try {
            //判断域是否存在
            String fieldName = fields.getField(key);
            if (fieldName != null) {
                // 通过域名获取所在页和坐标，左下角为起点
                int pageNo = fields.getFieldPositions(key).get(0).page;
                Rectangle signRect = fields.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //x = 20f;
                // y = 40f;
                // 读图片
                BASE64Decoder decoder = new BASE64Decoder();
                //解码为byte[]
//                byte[] bytes = decoder.decodeBuffer(value);
                Image image = Image.getInstance(bytes);
                // 获取操作的页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                // 根据域的大小缩放图片 再减去10防止域紧凑导致图片间隔小
                image.scaleToFit(signRect.getWidth() - 10, signRect.getHeight() - 10);
                // 添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
